home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
TextFormatter.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-26
|
7KB
|
345 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "TextFormatter.h"
#include "Class.h"
#include "Text.h"
#include "TextPainter.h"
#include "ObjArray.h"
#include "Math.h"
//---- TextFormatter -----------------------------------------------------------
NewAbstractMetaImpl(TextFormatter,Object, (TP(lines)));
ObjArray *TextFormatter::lines;
int TextFormatter::nLines;
ONEXIT(TextFormatter)
{
TextFormatter::Free();
}
TextFormatter::TextFormatter()
{
if (lines == 0)
lines= new ObjArray(32);
}
void TextFormatter::Free()
{
if (lines) {
lines->FreeAll();
SafeDelete(lines);
}
}
int TextFormatter::Format(Text *t, TextPainter *tp, int w, int from, int to)
{
nLines= 0;
DoFormat(t, tp, w, from, to);
return nLines;
}
void TextFormatter::AddBreak(
Text *t, TextPainter *tp, int from, int to, LineDesc &ld
)
{
if(nLines >= lines->Size())
lines->Expand((nLines)*2);
LineMark *lm= (LineMark*)lines->At(nLines);
if (lm == 0) {
lm= new LineMark;
lines->AtPut(nLines, lm);
}
tp->LineHeight(t, ld, from, to);
lm->ChangeMark(from, to-from, ld);
ld.Reset();
nLines++;
}
ObjArray *TextFormatter::GetLines()
{
return lines;
}
void TextFormatter::DoFormat(Text *, TextPainter *, int, int, int)
{
AbstractMethod("DoFormat");
}
//---- SimpleFormatter ---------------------------------------------------------
NewMetaImpl0(SimpleFormatter,TextFormatter);
SimpleFormatter::SimpleFormatter() : TextFormatter()
{
}
void SimpleFormatter::DoFormat(Text *t, TextPainter *tp, int, int from, int to)
{
AutoTextIter next(t, from, to);
register int ch, pos;
int start= from;
int wx= 0;
int cx= 0;
LineDesc maxld, ld;
while (TRUE) {
ch= next->Token(&wx, &ld);
maxld.Max(ld);
if (ch == cEOT) {
pos= next->GetPos();
if (start != pos)
AddBreak(t, tp, start, pos, maxld);
return;
}
if (ch == '\t')
wx= tp->Tabulate(t, cx, next->GetLastPos(), start);
if (Text::IsBreak(ch)) {
AddBreak(t, tp, start, next->GetPos(), maxld);
start= next->GetPos();
cx= 0;
} else
cx+= wx;
}
}
//---- class FoldingFormatter --------------------------------------------------
NewMetaImpl(FoldingFormatter,TextFormatter, (T(width), TP(text), T(start),
T(end), T(nWords),
T(wx), T(cx)));
FoldingFormatter::FoldingFormatter() : TextFormatter()
{
}
void FoldingFormatter::DoFormat(Text *t, TextPainter *tp, int w, int from, int to)
{
AutoTextIter next(t, from, to);
text= t;
register int ch, pos;
start= from;
nWords= wx= cx= 0;
LineDesc maxld, ld;
width= tp->GetFormatWidth(t, from, w);
while (TRUE) {
ch= next->Token(&wx, &ld);
// break character
if (wx > width && (next->GetPos()-next->GetLastPos() == 1)) {
Break(tp, start, next->GetLastPos(), maxld, w);
BreakCharacter(t, tp, start, maxld, w);
continue;
}
// word has to be folded on several lines
if (cx + wx > width && nWords == 0) {
end= next->GetPos();
BreakWord(t, tp, maxld, w);
wx= 0;
}
if (ch == cEOT) {
maxld.Max(ld);
pos= next->GetPos();
if (start != pos)
AddBreak(t, tp, start, pos, maxld);
return;
}
if (ch == '\t' || ch == ' ' || Text::IsBreak(ch)) {
maxld.Max(ld);
if (ch == '\t')
wx= tp->Tabulate(t, cx, next->GetLastPos(), start);
if (Text::IsBreak(ch) || (cx + wx > width))
Break(tp, start, next->GetPos(), maxld, w);
else {
cx+= wx;
nWords++;
}
} else if (cx + wx > width) {
Break(tp, start, next->GetLastPos(), maxld, w);
maxld= ld;
cx= wx;
} else {
maxld.Max(ld);
cx+= wx;
nWords++;
}
}
}
void FoldingFormatter::Break(
TextPainter *tp, int from, int to, LineDesc &maxld, int w
)
{
AddBreak(text, tp, from, to, maxld);
start= end= to;
width= tp->GetFormatWidth(text, end, w);
cx= 0;
nWords= 0;
}
void FoldingFormatter::BreakWord(Text *, TextPainter *tp, LineDesc &maxld, int w)
{
int l= 0, cw, ccw= 0;
AutoTextIter ti(text, start, end); // avoid nesting of nextc
LineDesc ld;
maxld.Reset();
while (ti(&cw, &ld) != cEOT) {
if (ccw + cw > width) {
end= ti->GetPos();
ccw= cw;
Break(tp, start, end-1, maxld, w);
maxld= ld;
} else {
maxld.Max(ld);
ccw+= cw;
}
}
cx= ccw;
end= ti->GetPos();
}
void FoldingFormatter::BreakCharacter(Text*, TextPainter *tp, int at, LineDesc &maxld, int w)
{
LineDesc ld;
int cw;
AutoTextIter ti(text, at, at+1);
maxld.Reset();
ti(&cw, &maxld);
Break(tp, at, at+1, maxld, w);
}
//---- abstract class TextPager ------------------------------------------
NewMetaImpl0(TextPager, Object);
TextPager::TextPager()
{
}
Rectangle TextPager::NextPageBreak(int, Rectangle pgr, StaticTextView *)
{
return pgr;
}
void TextPager::Repaginate(int)
{
}
//---- LinePager ---------------------------------------------------------
#include "StaticTView.h"
LinePager::LinePager()
{
}
Rectangle LinePager::NextPageBreak(int, Rectangle r, StaticTextView *tv)
{
int sl= tv->PointToLine(r.origin-tv->GetInnerOrigin());
int h= tv->LineToPoint(sl, FALSE, FALSE).y-r.origin.y;
int sh= h;
int ph= r.Height();
Text *text= tv->GetText();
for (int i= sl; i < tv->Lines(); i++) {
int dh= tv->LineHeight(i);
if (h + dh > ph) { // possible page break
if (h != sh) // page is not empty
r.extent.y= h;
break;
}
h+= dh;
}
return r;
}
//---- LineDesc --------------------------------------------------------
LineDesc::LineDesc(int b, int h)
{
lnAscent= b;
lnHeight= h;
}
void LineDesc::FromFont(Font *f)
{
lnAscent= f->Ascender();
lnHeight= f->Spacing();
}
void LineDesc::Reset()
{
lnAscent= lnHeight= 0;
}
void LineDesc::Max(Font *f)
{
int a= Math::Max(f->Ascender(), lnAscent);
int d= Math::Max(lnHeight-lnAscent, f->Spacing()-f->Ascender());
lnAscent= a;
lnHeight= a+d;
}
void LineDesc::Max(LineDesc ld)
{
int a= Math::Max(ld.lnAscent, lnAscent);
int d= Math::Max(lnHeight-lnAscent, ld.lnHeight - ld.lnAscent);
lnAscent= a;
lnHeight= a+d;
}
void LineDesc::Max(int ascent, int height)
{
int a= Math::Max(ascent, lnAscent);
int d= Math::Max(height-ascent, lnHeight-lnAscent);
lnAscent= a;
lnHeight= a+d;
}
//---- class LineMark ----------------------------------------------------------
NewMetaImpl0(LineMark, Mark);
int LineMark_lineChanged;
LineMark::LineMark(
LineDesc ldesc, int pos, int len, eMarkState s
) : Mark(pos, len, s)
{
ld= ldesc;
}
LineMark::LineMark()
{
}
void LineMark::Copy(LineMark *m)
{
Mark::ChangeMark(m->pos, m->len, m->state);
ld= m->ld;
}
void LineMark::ChangeMark( int pos, int len, LineDesc ldesc, eMarkState s)
{
Mark::ChangeMark(pos, len, s);
ld= ldesc;
}
bool LineMark::IsDifferent(LineMark *m)
{
return pos != m->pos
|| len != m->len
|| !ld.IsEqual(m->ld)
|| m->state != eStateNone
|| state != eStateNone;
}